/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.npmpackage.core.npmpackagecheck;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.npmpackage.api.entity.NpmInstallParameter;
import com.inspur.edp.web.npmpackage.api.entity.NpmPackageCheckUpdateOptions;
import com.inspur.edp.web.npmpackage.api.entity.NpmPackageConstants;
import com.inspur.edp.web.npmpackage.api.entity.packagejson.NpmPackageJsonDependencyInfo;
import com.inspur.edp.web.npmpackage.api.entity.packagejson.NpmPackageJsonInfo;
import com.inspur.edp.web.npmpackage.core.npminstall.NodeModulesPathGenerator;
import com.inspur.edp.web.npmpackage.core.npminstall.PackageJsonPathGenerator;
import io.iec.edp.caf.common.JSONSerializer;

import java.util.Iterator;
import java.util.Map;

/**
 * npm 设计时包版本检测
 *
 * @author noah
 */
public class NpmPackageCheck {
    /**
     * npm 设计时包版本检测
     *
     * @param checkUpdateOptions
     * @return
     */
    public static boolean check(NpmPackageCheckUpdateOptions checkUpdateOptions) {
        // 获取package.json 在server的部署位置
        String currentServerPath = FileUtility.getCurrentWorkPath(checkUpdateOptions.isUpgradeTool());
        String serverPackageJsonPath = PackageJsonPathGenerator.generate(currentServerPath, checkUpdateOptions.isMobile());

        NpmInstallParameter npmInstallParameter = new NpmInstallParameter();
        npmInstallParameter.setExecuteEnvironment(checkUpdateOptions.getExecuteEnvironment());
        npmInstallParameter.setMobile(checkUpdateOptions.isMobile());
        String parentNodeModulesPackageJsonPath = NodeModulesPathGenerator.generatePackageJsonPath(npmInstallParameter, currentServerPath);
        String nodeModulesWithPackageJsonPath = FileUtility.combine(parentNodeModulesPackageJsonPath, NpmPackageConstants.PackageJsonName);
        // 如果源文件不存在  那么无需进行比较
        if (!FileUtility.exists(serverPackageJsonPath)) {
            return true;
        }
        // 如果目标不存在 那么直接认为需要更新
        if (!FileUtility.exists(nodeModulesWithPackageJsonPath)) {
            return false;
        }

        // 如果两个文件都存在 那么比较文件内容

        String serverPackageJsonContent = FileUtility.readAsString(serverPackageJsonPath);
        String nodeModulesPackageJsonContent = FileUtility.readAsString(nodeModulesWithPackageJsonPath);


        NpmPackageJsonInfo serverPackageJsonInfo = packageJsonInfoGenerate(serverPackageJsonContent);
        NpmPackageJsonInfo nodeModulesPackageJsonInfo = packageJsonInfoGenerate(nodeModulesPackageJsonContent);

        if (serverPackageJsonInfo == null || nodeModulesPackageJsonInfo == null) {
            return false;
        }
        // 取反

        return serverPackageJsonInfo.equals(nodeModulesPackageJsonInfo);
    }

    public static NpmPackageJsonInfo packageJsonInfoGenerate(String serverPackageJsonContent) {
        NpmPackageJsonInfo packageJsonInfo = new NpmPackageJsonInfo();

        JsonNode jsonNode = JSONSerializer.deserialize(serverPackageJsonContent, JsonNode.class);
        String packageJsonName = jsonNode.get("name").asText();
        packageJsonInfo.setName(packageJsonName);

        String packageJsonVersion = jsonNode.get("version").asText();
        packageJsonInfo.setVersion(packageJsonVersion);

        String packageJsonDescription = jsonNode.get("description").asText();
        packageJsonInfo.setDescription(packageJsonDescription);

        String packageJsonAuthor = jsonNode.get("author").textValue();
        packageJsonInfo.setAuthor(packageJsonAuthor);

        String packageJsonLicense = jsonNode.get("license").asText();
        packageJsonInfo.setLicense(packageJsonLicense);

        ObjectNode dependenciesObjNode = (ObjectNode) jsonNode.get("dependencies");
        ObjectNode devDependenciesObjNode = (ObjectNode) jsonNode.get("devDependencies");

        if (dependenciesObjNode != null) {
            Iterator<Map.Entry<String, JsonNode>> iterator = dependenciesObjNode.fields();
            while (iterator.hasNext()) {
                Map.Entry<String, JsonNode> field = iterator.next();
                if (field != null && !StringUtility.isNullOrEmpty(field.getKey()) && !StringUtility.isNullOrEmpty(field.getValue().textValue())) {
                    packageJsonInfo.getDependencies().add(new NpmPackageJsonDependencyInfo(field.getKey(), field.getValue().textValue()));
                }
            }
        }

        if (devDependenciesObjNode != null) {
            Iterator<Map.Entry<String, JsonNode>> iterator = devDependenciesObjNode.fields();
            while (iterator.hasNext()) {
                Map.Entry<String, JsonNode> field = iterator.next();
                if (field != null && !StringUtility.isNullOrEmpty(field.getKey()) && !StringUtility.isNullOrEmpty(field.getValue().textValue())) {
                    packageJsonInfo.getDevDependencies().add(new NpmPackageJsonDependencyInfo(field.getKey(), field.getValue().textValue()));
                }
            }
        }

        return packageJsonInfo;
    }
}
